package com.stox.client.ui.javafx.watchlist.widget;

import java.util.List;
import java.util.ListIterator;

import javafx.collections.ListChangeListener;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;

import com.stox.client.api.core.Client;
import com.stox.client.ui.core.model.intf.HasNavigable;
import com.stox.client.ui.javafx.watchlist.model.OWatchlist;
import com.stox.shared.core.i18n.MessageSource;
import com.stox.shared.core.model.Scrip;
import com.stox.shared.core.model.intf.HasScrip;
import com.stox.shared.core.model.intf.Initializable;
import com.stox.shared.watchlist.model.Watchlist;
import com.stox.shared.watchlist.model.WatchlistEntry;

public class AddToWatchlistMenu extends Menu implements Initializable{

	private final HasScrip hasScrip;
	private final HasNavigable<? extends HasScrip> hasNavigable;
	private final EventHandler<ActionEvent> eventHandler = new EventHandler<ActionEvent>() {
		@Override
		public void handle(ActionEvent event) {
			MenuItem item = (MenuItem) event.getSource();
			Watchlist watchlist = (Watchlist) item.getUserData();

			if (null != hasNavigable) {
				List<? extends HasScrip> hasScrips = hasNavigable.getNavigable().currentAllSelection();
				for (HasScrip hasScrip : hasScrips) {
					if (null != hasScrip && null != hasScrip.getScripId()) {
						addWatchlistEntry(watchlist.getId(), hasScrip.getScripId());
					}
				}
			} else if (null != hasScrip) {
				Scrip scrip = hasScrip.getScrip();
				if (null != scrip) {
					addWatchlistEntry(watchlist.getId(), scrip.getId());
				}
			}
		}
	};

	public AddToWatchlistMenu(HasScrip hasScrip, HasNavigable<? extends HasScrip> hasNavigable) {
		super(MessageSource.get("Add.to.Watchlist"));
		this.hasScrip = hasScrip;
		this.hasNavigable = hasNavigable;
	}
	
	private boolean initialized = false;
	@Override
	public void initialize(){
		if (!initialized) {
			initialized = true;
			OWatchlist.fetchAll();
			for (OWatchlist watchlist : OWatchlist.ALL) {
				addWatchlist(watchlist);
			}
			OWatchlist.ALL.addListener(new ListChangeListener<OWatchlist>() {
				@Override
				public void onChanged(Change<? extends OWatchlist> change) {
					while (change.next()) {
						if (change.wasAdded()) {
							for (OWatchlist watchlist : change.getAddedSubList()) {
								addWatchlist(watchlist);
							}
						} else if (change.wasRemoved()) {
							for (OWatchlist watchlist : change.getRemoved()) {
								deleteWatchlist(watchlist.getId());
							}
						}
					}
				}
			});
		}
	}

	private void addWatchlistEntry(Long watchlistId, Long scripId) {
		WatchlistEntry watchlistEntry = new WatchlistEntry(scripId, watchlistId);
		Long id = Client.WATCHLIST_ENTRY.saveOrUpdate(watchlistEntry);
		watchlistEntry.setId(id);
		OWatchlist watchlist = OWatchlist.getWatchlistById(watchlistId);
		watchlist.getEntries().add(watchlistEntry);
	}

	public void addWatchlist(OWatchlist watchlist) {
		MenuItem item = new MenuItem();
		item.textProperty().bind(watchlist.nameProperty());
		item.setUserData(watchlist);
		item.setOnAction(eventHandler);
		getItems().add(item);
	}

	public void deleteWatchlist(Long id) {
		ListIterator<MenuItem> iterator = getItems().listIterator();
		while (iterator.hasNext()) {
			MenuItem item = iterator.next();
			Watchlist userObject = (Watchlist) item.getUserData();
			if (id.equals(userObject.getId())) {
				iterator.remove();
				break;
			}
		}
	}

}
